package cooperate

import (
	"bytes"
	"context"
	"fmt"
	"runtime/debug"
	"strings"
	"sync"

	"gddgame.cc/galaxy/binocle"
	"gddgame.cc/galaxy/common/feature/orbit/chess_protocol"
	"gddgame.cc/galaxy/common/namespaces/cooperate/structure"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/serialize"
	"github.com/gomodule/redigo/redis"
)

type LogicExecute struct {
	execute *structure.Execute

	TypeDefinedManager
	MapDefined

	agent binocle.App
	Redis *redis.Pool

	DataTypeMap map[structure.PublicDataType]*DataTypeContainer

	baseConn      structure.SafeConn
	baseConnMutex sync.Mutex

	connPool sync.Pool

	ctx          context.Context
	inlineCtx    context.Context
	inlineCancel context.CancelFunc
	needStop     bool

	operateQueue     *utils.SafePriorityNodeQueue
	operateChan      chan struct{}
	operateBucket    *utils.ThreaderBucket
	operateConn      []structure.SafeConn
	taskChan         chan *TaskBuilder
	taskGetChan      chan chan []*structure.TaskInfo
	taskFinishChan   chan string
	taskRestoreChan  chan string
	taskTime         int64
	taskChanPool     sync.Pool
	scheduleChan     chan *ScheduleBuilder
	scheduleTime     int64
	scheduleDiff     int64
	scheduleAddition int64
	schedulePool     *utils.ThreaderPool

	Notice OnUpdateNoticeInf
}

func (logic *LogicExecute) Execute() *structure.Execute {
	return logic.execute
}

func (logic *LogicExecute) ScheduleTime() int64 {
	return logic.scheduleTime
}

func (logic *LogicExecute) TaskTime() int64 {
	return logic.taskTime
}

func (logic *LogicExecute) IncrTypeId(mapNoId string, t structure.PublicDataType) int {
	fd := logic.GetFieldsDefine(t)
	if !fd.IsMap {
		mapNoId = ""
	}
	logic.baseConnMutex.Lock()
	id := logic.execute.IncrTypeId(logic.baseConn, t, mapNoId)
	logic.baseConnMutex.Unlock()
	return id
}

func (logic *LogicExecute) GetList(mapNoId string, data structure.Data, depend *BeDependDefine) []interface{} {
	if depend.BeDependType == structure.MapType && logic.IsNodeType(depend.DependType) {
		v := []interface{}{}
		logic.baseConnMutex.Lock()
		logic.execute.Traverse(logic.baseConn, depend.DependType, mapNoId+"/", func(id interface{}) {
			v = append(v, MapNode{
				MapNoId:  mapNoId,
				Position: utils.ToBytes(id),
			})
		})
		logic.baseConnMutex.Unlock()
		return v
	} else {
		tmp := structure.NewBaseDataFrom(data)
		//fmt.Println(data, tmp)
		tmp.Id, _ = logic.AdditionMapId(mapNoId, tmp.DataType, tmp.Id)
		logic.baseConnMutex.Lock()
		v := logic.execute.GetDepends(logic.baseConn, tmp, depend.BeDepend)
		logic.baseConnMutex.Unlock()
		if v == nil {
			return []interface{}{}
		}
		//fmt.Println("getlist", mapNoId, depend, v, data, tmp)
		if depend.DependIsPosition {
			for index, id := range v {
				sid := utils.ToString(id)
				ii := strings.Index(sid, "/")
				//fmt.Println("index", index, id, sid, sid[0:ii-1], sid[ii:])
				v[index] = MapNode{
					MapNoId:  sid[0:ii],
					Position: utils.ToBytes(sid[ii+1:]),
				}
			}
		} else if depend.DependIsNo {
			for index, id := range v {
				v[index] = utils.ToInt(id)
			}
		} else if depend.DependIsId {
			for index, id := range v {
				v[index] = utils.ToString(id)
			}
		}
		return v
	}
}
func (logic *LogicExecute) depend(dataType structure.PublicDataType, key string) *BeDependDefine {
	fd := logic.GetFieldsDefine(dataType)
	var depend *BeDependDefine
	if fd != nil {
		dependIndex := fd.BeDependMap[key]
		depend = fd.BeDepends[dependIndex]
	}
	if depend == nil {
		depend = logic.DefaultBeDepend(dataType, key)
	}
	return depend
}
func (logic *LogicExecute) ListData(mapInstance MapProxy, dataType structure.PublicDataType, ids []interface{}) []PropsInstance {
	list := make([]PropsInstance, len(ids))
	for index, id := range ids {
		list[index] = logic.GetDetailCache(mapInstance, structure.NewBaseData(dataType, id))
	}
	return list
}
func (logic *LogicExecute) ListDepend(mapInstance MapProxy, dataType structure.PublicDataType, id interface{}, key string) []PropsInstance {
	depend := logic.depend(dataType, key)
	itemData := structure.NewBaseData(dataType, id)
	item := logic.GetDetailCache(mapInstance, itemData)
	var ll []interface{}
	if item != nil {
		ll = item.ListDepend(depend)
	}
	if ll == nil {
		ll = logic.GetList(mapInstance.GetMapNoId(), itemData, depend)
	}
	list := make([]PropsInstance, len(ll))
	for index, id := range ll {
		if depend.DependIsId {
			list[index] = logic.GetDetailCache(mapInstance, structure.NewBaseData(depend.DependType, id.(string)))
		} else if depend.DependIsNo {
			list[index] = logic.GetDetailCache(mapInstance, structure.NewBaseData(depend.DependType, id.(int)))
		} else if depend.DependIsPosition {
			node := id.(MapNode)
			list[index] = logic.GetDetailCache(mapInstance, structure.NewBaseData(depend.DependType, node.Position))
		}
		if list[index] == nil {
			fmt.Println("ownnode", dataType, depend.DependType, id)
		}
	}
	return list
}

func (logic *LogicExecute) clearDetailCache(mapNoId string, data structure.Data) {
	idString, _ := logic.AdditionMapId(mapNoId, data.GetDataType(), data.GetId())
	mm := logic.DataTypeMap[data.GetDataType()]
	mm.Mutex.Lock()
	delete(mm.Cache, idString)
	mm.Mutex.Unlock()
}
func (logic *LogicExecute) GetDetailTmp(mapInstance MapBase, data structure.Data, dd structure.Data) PropsInstance {
	//fmt.Println(mapNoId, data)
	if dd == nil {
		idString, _ := logic.AdditionMapId(mapInstance.GetMapNoId(), data.GetDataType(), data.GetId())
		dd = structure.NewBaseData(data.GetDataType(), idString)
	}
	//startTime := time.Now()
	conn := logic.execute.Transaction()
	conn.Connect()
	result := logic.execute.Get(conn, dd)
	//fmt.Println("get", dd, result)
	extendMap := map[structure.ExtendType]interface{}{}
	if result == nil || len(result) == 0 {
		if !logic.IsNodeType(data.GetDataType()) && data.GetDataType() != structure.MapType && data.GetDataType() != MapContentType {
			//fmt.Println("get empty", data, dd)
			//debug.PrintStack()
			_ = conn.Close()
			return nil
		} else {
			//fmt.Println("get empty", data, dd)
			//debug.PrintStack()
		}
		result = map[string]interface{}{}
	}
	fd := logic.GetFieldsDefine(data.GetDataType())
	propInstance := NewPropInstance(logic, fd, data, result)

	//fmt.Println("get", propInstance, data, propInstance.Data())
	if len(result) > 0 {
		if fd != nil {
			for _, extendDefine := range fd.NoticeExtendMap {
				if extendDefine.fun == nil {
					continue
				}
				extendMap[extendDefine.Extend] = extendDefine.fun(logic.execute, conn, propInstance, extendDefine.Extend)
			}
		}
	}

	_ = conn.Close()
	v := logic.GetDetail(mapInstance, propInstance, extendMap)
	return v
}
func (logic *LogicExecute) GetDetailCache(mapInstance MapBase, data structure.Data) PropsInstance {
	//fmt.Println(mapNoId, data)
	idString, _ := logic.AdditionMapId(mapInstance.GetMapNoId(), data.GetDataType(), data.GetId())
	mm := logic.DataTypeMap[data.GetDataType()]
	mm.Mutex.RLock()
	v, _ := mm.Cache[idString]
	mm.Mutex.RUnlock()
	//fmt.Println("get", data, v)
	if v == nil {
		dd := structure.NewBaseData(data.GetDataType(), idString)
		v = logic.GetDetailTmp(mapInstance, data, dd)
		mm.Mutex.Lock()
		vv, _ := mm.Cache[idString]
		if vv == nil {
			mm.Cache[idString] = v
		} else {
			v = vv
		}
		mm.Mutex.Unlock()
		//endTime = time.Now()
		//p3 := endTime.Sub(startTime)
		//
		//if p3 > 10*time.Millisecond {
		//	fmt.Println("get detail", p1, p2, p3)
		//}
	}
	//fmt.Println("get", data, v, v.Data(), v.GetId())
	return v
}

func (logic *LogicExecute) UpdateDetailCache(current bool, mapInstance MapProxy, data structure.Data, update *UpdateContent) (PropsInstance, *chess_protocol.UpdatePublicData, bool) {
	idString, _ := logic.AdditionMapId(mapInstance.GetMapNoId(), data.GetDataType(), data.GetId())
	mm := logic.DataTypeMap[data.GetDataType()]
	var v PropsInstance
	mm.Mutex.RLock()
	v, _ = mm.Cache[idString]
	mm.Mutex.RUnlock()
	updateFlag := false
	if v == nil {
		// 清理模式，不创建
		if update.Mode == ClearUpdateMode {
			return nil, nil, true
		}
		dd := structure.NewBaseData(data.GetDataType(), idString)
		var result map[string]interface{}
		var conn structure.SafeConn
		if update.Mode != CreateUpdateMode {
			conn = logic.execute.Transaction()
			conn.Connect()
			result = logic.execute.Get(conn, dd)
		}
		extendMap := map[structure.ExtendType]interface{}{}
		if result == nil || len(result) == 0 {
			result = map[string]interface{}{}
		}
		//dd := structure.NewBaseData(data.GetDataType(), idString)
		fd := logic.GetFieldsDefine(data.GetDataType())
		propInstance := NewPropInstance(logic, fd, data, result)
		if len(result) > 0 {
			if fd != nil {
				for _, extendDefine := range fd.NoticeExtendMap {
					if extendDefine.fun == nil {
						continue
					}
					extendMap[extendDefine.Extend] = extendDefine.fun(logic.execute, conn, propInstance, extendDefine.Extend)
				}
			}
		}
		if conn != nil {
			_ = conn.Close()
		}
		updateFlag = true
		logic.UpdateProp(propInstance, update)
		v = logic.GetDetail(mapInstance, propInstance, extendMap)
		//fmt.Println("update", idString)
		mm.Mutex.Lock()
		vv, _ := mm.Cache[idString]
		if vv == nil {
			mm.Cache[idString] = v
		} else {
			v = vv
		}
		mm.Mutex.Unlock()
		//fmt.Println("update1", v)
	}
	var content *chess_protocol.UpdatePublicData
	var deleteStatus bool
	if update.Mode == DeleteUpdateMode {
		// 删除
		mm.Mutex.Lock()
		delete(mm.Cache, idString)
		mm.Mutex.Unlock()
		deleteStatus = true
	} else {
		//fmt.Println("update2", v)
		if !updateFlag {
			logic.UpdateProp(v, update)
		}
		content = logic.UpdateDetail(mapInstance, v, update)
		//fmt.Println("update", v.Data(), update.Inherit, update.Props, update.UpdatePublicData)
		//if update.Inherit {
		//}
	}
	if content == nil {
		content = &chess_protocol.UpdatePublicData{}
	}

	switch update.Mode {
	case CreateUpdateMode:
		//fmt.Println("create", v.Data(), v.ToBytes(Position), v.ToInt(AccountDataType))
		mapInstance.OnCreateAfter(v, current)
	case ResetUpdateMode:
		mapInstance.OnResetAfter(v, current)
	case DeleteUpdateMode:
		mapInstance.OnDestroyAfter(v, current)
	default:
		mapInstance.OnUpdateData(v, current)
	}
	return v, content, deleteStatus
}

func (logic *LogicExecute) GetPropsCache(mapInstance MapProxy, data structure.Data, props []string) map[string]interface{} {
	instance := logic.GetDetailCache(mapInstance, data)
	if instance == nil {
		return map[string]interface{}{}
	}
	return instance.GetProps(props)
}

func (logic *LogicExecute) GetPropCache(mapInstance MapProxy, data structure.Data, prop string) interface{} {
	instance := logic.GetDetailCache(mapInstance, data)
	if instance == nil {
		return nil
	}
	return instance.GetProp(prop)
}

func (logic *LogicExecute) GetEventsCache(mapInstance MapProxy, data structure.Data, events []byte) []*structure.EventData {
	info := logic.GetDetailCache(mapInstance, data)
	if info == nil {
		//fmt.Println("events", data)
		//debug.PrintStack()
		return []*structure.EventData{}
	}
	return info.GetEvents(events)
}

func (logic *LogicExecute) GetEventCache(mapInstance MapProxy, data structure.Data, event byte) *structure.EventData {
	info := logic.GetDetailCache(mapInstance, data)
	if info == nil {
		//fmt.Println("event", data)
		//debug.PrintStack()
		return nil
	}
	return info.GetEvent(event)
}

func (logic *LogicExecute) BindEvent(conn structure.SafeConn, mapNoId string, data structure.Data, event byte, mode structure.EventMode, content []byte) {
	idString, _ := logic.AdditionMapId(mapNoId, data.GetDataType(), data.GetId())
	eventData := logic.execute.BindEvent(conn, structure.NewBaseData(data.GetDataType(), idString), event, mode, content)

	logic.Notice.OnUpdate(&UpdateNotice{
		MapNoId: mapNoId,
		List: []NoticeContent{{
			OldAccountId: 0,
			NewAccountId: 0,
			Data:         *structure.NewBaseDataFrom(data),
			Content: UpdateContent{
				Event: []structure.EventData{*eventData},
			},
		}},
	})
}

func (logic *LogicExecute) ClearEvent(mapNoId string, data structure.Data, event byte) {
	operates := []UpdateOperateContent{UpdateOperateContent{
		Operate: ClearEvent,
		Value:   event,
	}}
	operateData := &UpdateOperateData{
		Data:     *structure.NewBaseDataFrom(data),
		Operates: operates,
	}
	updateData := OperateContent{
		MapNoId: mapNoId,
		Target:  &operateData.Data,
		Operates: []OperateData{
			NewOperateData(BatchUpdateOperate, operateData),
		},
	}
	// 不做传送事件
	logic.PushOperate(updateData, 0)
}

func (logic *LogicExecute) ScheduleCheck(info *structure.ScheduleInfo) CheckData {
	versionCheck := CheckData{
		Data: info.ScheduleData,
		Checks: []CheckContent{
			{
				Check: EqualCheck,
				Key:   "version",
				Value: info.Version,
			},
		}}
	return versionCheck
}

func (logic *LogicExecute) AnlyzeSchedule(mapInstance *MapInstance, info *structure.ScheduleInfo) {
	slot := serialize.GetSlot()

	//v := time.Now().UnixNano()/1e6 - info.Time
	//if v > 1000 {
	//	fmt.Println("cooperate schedule", info.Time, info.Schedule, "big", v)
	//}
	switch info.Schedule {
	case OnceSchedule:
		var content OnceScheduleContent
		if err := slot.Set(&content); err != nil {
			fmt.Println("once", err)
		} else if err := slot.Unmarshal(info.Data); err != nil {
			fmt.Println("once", err)
		} else {
			logic.Mode(mapInstance, info.From, info.Target, content.Event, info.Time, NewModeExtend(info.Params, info.MapNoId, nil, nil))
		}
	case RepeatSchedule:
		var content RepeatScheduleContent
		if err := slot.Set(&content); err != nil {
			fmt.Println("repeat", err)
		} else if err := slot.Unmarshal(info.Data); err != nil {
			fmt.Println("repeat", err)
		} else if logic.Mode(mapInstance, info.From, info.Target, content.Event, info.Time, NewModeExtend(info.Params, info.MapNoId, nil, nil)) {
			if content.EndTime > 0 {
				content.EndTime = logic.FormatTime(content.EndTime)
				if content.EndTime < logic.CurrentTime() {
					break
				}
			}
			sslot := serialize.GetSlot()
			_ = sslot.Set(&content)
			b, _ := sslot.Marshal()
			info.Data = b
			scheduleBuilder := logic.ScheduleBuilder()
			scheduleBuilder.BindInfo(*info).Schedule(info.Time+content.Repeat, nil, info.ScheduleDelay)
		}
	case RepeatEverySchedule:
		var content RepeatEveryScheduleContent
		if err := slot.Set(&content); err != nil {
			fmt.Println("repeatEvery", err)
		} else if err := slot.Unmarshal(info.Data); err != nil {
			fmt.Println("repeatEvery", err)
		} else if logic.checkList(mapInstance, content.Checks) {
			depend := logic.DefaultDepend(mapInstance.Data.DataType, content.DependKey)
			list := logic.GetList(info.MapNoId, mapInstance.Data, depend.Be)
			for _, id := range list {
				logic.PushOperate(OperateContent{
					MapNoId: info.MapNoId,
					Checks:  nil,
					From:    info.From,
					Target:  info.Target,
					Operates: []OperateData{
						NewOperateData(BatchUpdateOperate, &UpdateOperateData{
							Data:     *structure.NewBaseData(depend.Be.DependType, id),
							Operates: content.Operates,
						},
						)},
				}, 0)
			}
			if content.EndTime > 0 {
				content.EndTime = logic.FormatTime(content.EndTime)
				if content.EndTime < logic.CurrentTime() {
					break
				}
			}
			sslot := serialize.GetSlot()
			_ = sslot.Set(&content)
			b, _ := sslot.Marshal()
			info.Data = b
			scheduleBuilder := logic.ScheduleBuilder()
			scheduleBuilder.BindInfo(*info).Schedule(info.Time+content.Repeat, nil, info.ScheduleDelay)
		}
	case MoveSchedule:
		var content MoveScheduleContent
		if err := slot.Set(&content); err != nil {
			fmt.Println("move set", err)
		} else if err := slot.Unmarshal(info.Data); err != nil {
			fmt.Println("move unmarshal", err)
		} else {
			//fmt.Println("move", info.Target, info.Key, content.Index, info.Time)
			mapInstance.Move(info, &content)
		}
	case TouchSchedule:
		var content TouchScheduleContent
		if err := slot.Set(&content); err != nil {
			fmt.Println("touch", err)
		} else if err := slot.Unmarshal(info.Data); err != nil {
			debug.PrintStack()
			fmt.Println("touch", err)
		} else {
			mapInstance.Touch(info, &content)
		}
	case CustomSchedule:
		var content CustomScheduleContent
		if err := slot.Set(&content); err != nil {
			fmt.Println("custom", err)
		} else if err := slot.Unmarshal(info.Data); err != nil {
			debug.PrintStack()
			fmt.Println("custom", err)
		} else {
			if content.Async {
				go func() {
					mapInstance.Custom(info, &content)
				}()
			} else {
				mapInstance.Custom(info, &content)
			}
		}
	default:
		fmt.Println("sch", info.Schedule, info)
	}
}

// 当前环境提交的Schedule和task，依旧可以在当前环境执行
func (logic *LogicExecute) PushSchedule(schedule *ScheduleBuilder) {
	logic.scheduleChan <- schedule
}

func (logic *LogicExecute) PushTask(task *TaskBuilder) {
	logic.taskChan <- task
}

func (logic *LogicExecute) PushOperate(content OperateContent, targetTime int64) {
	//logic.queue.Push(content, logic.FromStartUp(targetTime))
	logic.Notice.OnQueue(&Queue{
		Content:    content,
		TargetTime: targetTime,
	})
}

func (logic *LogicExecute) PushNotice(mapNoId string, accountId int, event byte, content []byte) {
	logic.Notice.OnNotice(&Notice{
		MapNoId:   mapNoId,
		AccountId: accountId,
		Event:     event,
		Content:   content,
	})
}

func (logic *LogicExecute) PopQueue(queue Queue) {
	logic.operateQueue.Push(&queue.Content, logic.FromStartUp(queue.TargetTime))
}

func (logic *LogicExecute) Mode(mapInstance MapProxy, from structure.Data, target structure.Data, eventProp structure.EventData, targetTime int64, extend *ModeExtend) bool {
	slot := serialize.GetSlot()
	r := false
	if extend.Checks != nil {
		if !logic.checkList(mapInstance, extend.Checks) {
			goto Return
		}
	}

	switch eventProp.Mode {
	case OperateMode:
		var content OperateContent
		_ = slot.Set(&content)
		if err := slot.Unmarshal(eventProp.Content); err != nil {
			fmt.Println("mode operate", err)
			goto Return
		}
		if logic.checkList(mapInstance, content.Checks) {
			if content.From != nil {
				from = content.From
			}
			content.Target = structure.NewBaseData(target.GetDataType(), target.GetId())
			if content.Message != nil {
				//fmt.Println("mode message", content.Message)
				if extend != nil {
					content.Message.Message.Params = extend.Params
					if extend.Content != nil {
						b, err := extend.Content.MarshalMsg(nil)
						if err != nil {
							fmt.Println("extend msg error", err)
						}
						content.Message.Message.Content = b
					}
					content.Message.Position = extend.Position
					content.Message.Persistent = extend.Persistent
				}
			}
			//fmt.Println("mode:", content.MapNoId, extend)
			if content.MapNoId == "" && extend != nil {
				content.MapNoId = extend.MapNoId
			}
			if extend != nil && extend.UpdateOperate != nil {
				// 将message合并到update
				if content.Message != nil {
					if content.Message.Data == nil || extend.UpdateOperate.Data.DataType == content.Message.Data.DataType {
						//fmt.Println("merge", content.Message, extend.UpdateOperate)
						extend.UpdateOperate.Message = content.Message.Message
						content.Message = nil
					}
				}
				if !content.MergeUpdate(slot, extend.UpdateOperate) {
					content.Operates = append(content.Operates, NewOperateData(BatchUpdateOperate, extend.UpdateOperate))
				}
			}
			//fmt.Println("content", content, content.Message)
			//if targetTime-logic.CurrentTime() < -500 {
			//fmt.Println("operate push", target, targetTime, targetTime-logic.CurrentTime(), 1)
			//}
			logic.PushOperate(content, targetTime)
			r = true
		}
	case TaskMode:
		var content TaskContent
		_ = slot.Set(&content)
		if err := slot.Unmarshal(eventProp.Content); err != nil {
			fmt.Println("mode task", err)
			goto Return
		}
		if logic.checkList(mapInstance, content.Checks) {
			if content.From != nil {
				from = content.From
			}
			builder := logic.TaskBuilder()
			builder.From(structure.NewBaseDataFrom(from))
			builder.BindMapNoId(extend.MapNoId).Bind(content.Task, content.Content).Task(targetTime, extend.Params)
			//fmt.Println("mode task", target, targetTime, logic.CurrentTime())
			r = true
		}
	case ScheduleMode:
		var content ScheduleContent
		_ = slot.Set(&content)
		if err := slot.Unmarshal(eventProp.Content); err != nil {
			fmt.Println("mode schedule", err)
			goto Return
		}
		if logic.checkList(mapInstance, content.Checks) {
			if content.From != nil {
				from = content.From
			}
			if content.Target != nil {
				target = content.Target
			}
			builder := logic.ScheduleBuilder()
			builder.BindMapNoId(extend.MapNoId).From(structure.NewBaseDataFrom(from)).Target(*structure.NewBaseDataFrom(target)).Key(content.Key).Bind(content.Schedule, content.Content).Schedule(content.Time, extend.Params, content.Delay)
			r = true
		}
	case BindEventMode:
		var content EventContent
		_ = slot.Set(&content)
		if err := slot.Unmarshal(eventProp.Content); err != nil {
			fmt.Println("mode bind event", err)
			goto Return
		}
		if logic.checkList(mapInstance, content.Checks) {
			if content.Current != nil && len(content.Current) > 0 {
				eps := logic.GetEventsCache(mapInstance, target, content.Current)
				if eps != nil && len(eps) > 0 {
					for index, _ := range content.Current {
						ep := eps[index]
						if ep == nil {
							//fmt.Println("event mode", target, content.Current, eps)
							//debug.PrintStack()
							goto Return
						}
						r = logic.Mode(mapInstance, from, target, *ep, targetTime, extend)
					}
				}

			}
			if content.Events != nil && len(content.Events) > 0 {
				for _, ed := range content.Events {
					eps := logic.GetEventsCache(mapInstance, &ed.Data, ed.Events)
					if eps != nil && len(eps) > 0 {
						for index, _ := range ed.Events {
							ep := eps[index]
							if ep == nil {
								//fmt.Println("event mode", ed.Data, ed.Events, eps)
								//debug.PrintStack()
								goto Return
							}
							r = logic.Mode(mapInstance, from, &ed.Data, *ep, targetTime, extend)
						}
					}
				}
			}
		}
	case QueryMode:
		var content QueryContent
		_ = slot.Set(&content)
		if err := slot.Unmarshal(eventProp.Content); err != nil {
			fmt.Println("mode schedule", err)
			goto Return
		}
		if logic.checkList(mapInstance, content.Checks) {
			result := mapInstance.OnQuery(content.AccountId, content.Identity, content.Event, content.Params)
			switch r := result.(type) {
			case error:
				mapInstance.OnError(content.AccountId, r)
			}
		}
	}
Return:
	if extend != nil {
	}
	slot.Release()
	return r
}

func (logic *LogicExecute) TransformMap(allMap map[string][]interface{}, ps string, item interface{}) {
	all := allMap[ps]
	if all == nil {
		all = []interface{}{}
	}
	all = append(all, item)
	allMap[ps] = all
}

func (logic *LogicExecute) transformOperate(mapInstance *MapInstance, od OperateData, data PropsInstance, allMap map[string][]interface{}, notices []NoticeContent) (map[string][]interface{}, []NoticeContent) {
	switch od.Operate {
	case CreateOperate:
		createOperateData := od.inline.(*CreateOperateData)
		fd := logic.GetFieldsDefine(createOperateData.Data.DataType)
		noticeData := UpdateContent{
			UpdatePublicData: &chess_protocol.UpdatePublicData{
				Props: []chess_protocol.UpdateProp{},
			},
			Mode: CreateUpdateMode,
		}

		chessData := &chess_protocol.Data{
			Range:    logic.DataRange(data),
			Position: createOperateData.Position,
		}
		for i, key := range createOperateData.InfoKey {
			if fd == nil {
				noticeData.Props = append(noticeData.Props, UpdateField{
					Key:   key,
					Value: createOperateData.Infos[i],
				})
				continue
			}
			if index, ok := fd.NoticeProp[key]; ok {
				noticeData.UpdatePublicData.Props = append(noticeData.UpdatePublicData.Props, chess_protocol.UpdateProp{
					Key:   byte(index),
					Value: createOperateData.Infos[i],
				})
			} else {
				noticeData.Props = append(noticeData.Props, UpdateField{
					Key:   key,
					Value: createOperateData.Infos[i],
				})
			}
			if index, ok := fd.ChessProp[key]; ok {
				if len(chessData.Props) <= int(index) {
					chessData.Props = append(chessData.Props, make([]interface{}, int(index)-len(chessData.Props)+1)...)
				}
				chessData.Props[index] = createOperateData.Infos[i]
			}
		}

		for index, value := range createOperateData.Extends {
			if len(createOperateData.ExtendKey) == index {
				break
			}
			extend := structure.ExtendType(createOperateData.ExtendKey[index])
			if ii, ok := fd.NoticeExtend[extend]; ok {
				noticeData.Reset = append(noticeData.Reset, chess_protocol.ResetExtend{Index: ii, List: value})
			}
			if ii, ok := fd.ChessExtend[extend]; ok {
				if len(chessData.Extend) <= int(ii) {
					chessData.Extend = append(chessData.Extend, make([][]chess_protocol.ExtendItem, int(ii)-len(chessData.Extend)+1)...)
				}
				//fmt.Println("extend", extend, createOperateData.Data.DataType, ii)
				chessData.Extend[ii] = value
			}
		}
		item := &chess_protocol.SingleData{
			DataType: byte(createOperateData.Data.DataType),
			Id:       createOperateData.Data.Id,
			Data:     chessData,
		}
		accountId := createOperateData.accountId
		notice := NoticeContent{
			OldAccountId: 0,
			NewAccountId: accountId,
			Data:         createOperateData.Data,
			Content:      noticeData,
		}
		for _, operate := range createOperateData.updateOperates {
			if fd == nil {
				continue
			}
			if operate.Props != nil {
				// 不用加入notice，服务端逻辑会在更新后依旧更新对应值，这里的目的是更新到同步端
				// 同步到其他服务端冗余数据，会自己在更新notice时处理关联属性，不用计算
				for field, prop := range operate.Props {
					if index, ok := fd.ChessProp[field]; ok {
						//fmt.Println("create prop", index, field, prop)
						if len(chessData.Props) <= int(index) {
							chessData.Props = append(chessData.Props, make([]interface{}, int(index)-len(chessData.Props)+1)...)
						}
						chessData.Props[index] = prop
					}
				}
				continue
			}
			switch operate.Operate {
			case ChangeList:
				fallthrough
			case ChangeListTime:
				extend := structure.ExtendType(operate.Key)
				if ii, ok := fd.NoticeExtend[extend]; ok {
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: ii,
						Key:   operate.Index,
						Value: operate.Value,
					})
				}
				if ii, ok := fd.ChessExtend[extend]; ok {
					if len(chessData.Extend) <= int(ii) {
						chessData.Extend = append(chessData.Extend, make([][]chess_protocol.ExtendItem, int(ii)-len(chessData.Extend)+1)...)
					}
					//fmt.Println("extend", extend, createOperateData.Data.DataType, ii)
					if chessData.Extend[ii] == nil {
						chessData.Extend[ii] = make([]chess_protocol.ExtendItem, operate.Index+1)
					} else if len(chessData.Extend[ii]) <= operate.Index {
						chessData.Extend[ii] = append(chessData.Extend[ii], make([]chess_protocol.ExtendItem, operate.Index-len(chessData.Extend)+1)...)
					}
					chessData.Extend[ii][operate.Index] = chess_protocol.ExtendItem{No: operate.Index, Value: operate.Value}
				}
			case RemoveDepend:
				n, pp, ii := logic.removeDepend(accountId, &createOperateData.Data, &operate, &notice, &noticeData, fd, mapInstance, allMap)
				if n == nil {
					continue
				}
				notices = append(notices, *n)
				if ii == nil {
					continue
				}
				ps := mapInstance.Location(pp)

				logic.TransformMap(allMap, ps, ii)
			case AddDepend:
				n, pp, ii := logic.addDepend(accountId, &createOperateData.Data, &operate, &notice, &noticeData, fd, mapInstance, allMap)
				if n == nil {
					continue
				}
				notices = append(notices, *n)
				if ii == nil {
					continue
				}
				ps := mapInstance.Location(pp)
				logic.TransformMap(allMap, ps, ii)
			}
		}
		notice.Content = noticeData
		notices = append(notices, notice)
		//fmt.Println("create", notice)
		if fd == nil {
			goto Return
		}
		if !fd.IsChess {
			goto Return
		}
		if createOperateData.Position == nil || len(createOperateData.Position) == 0 {
			goto Return
		}
		if !data.ToBool(Ignore) {
			ps := mapInstance.Location(createOperateData.Position)
			logic.TransformMap(allMap, ps, item)
		}
	case ResetOperate:
		resetOperateData := od.inline.(*ResetOperateData)
		fd := logic.GetFieldsDefine(resetOperateData.Data.DataType)
		accountId := data.ToInt(logic.execute.GetDataType(AccountType))
		noticeData := UpdateContent{
			UpdatePublicData: &chess_protocol.UpdatePublicData{
				Props: []chess_protocol.UpdateProp{},
			},
			Mode: ResetUpdateMode,
		}
		chessData := chess_protocol.UpdatePublicData{
			Props: []chess_protocol.UpdateProp{},
		}
		notice := NoticeContent{
			OldAccountId: accountId,
			NewAccountId: accountId,
			Data:         resetOperateData.Data,
		}
		for i, key := range resetOperateData.InfoKey {
			if fd == nil {
				noticeData.Props = append(noticeData.Props, UpdateField{
					Key:   key,
					Value: resetOperateData.Infos[i],
				})
				continue
			}
			if index, ok := fd.NoticeProp[key]; ok {
				noticeData.UpdatePublicData.Props = append(noticeData.UpdatePublicData.Props, chess_protocol.UpdateProp{
					Key:   byte(index),
					Value: resetOperateData.Infos[i],
				})
			} else {
				noticeData.Props = append(noticeData.Props, UpdateField{
					Key:   key,
					Value: resetOperateData.Infos[i],
				})
			}
			if index, ok := fd.ChessProp[key]; ok {
				chessData.Props = append(chessData.Props, chess_protocol.UpdateProp{
					Key:   byte(index),
					Value: resetOperateData.Infos[i],
				})
			}
		}
		for _, operate := range resetOperateData.updateOperates {
			if fd == nil {
				continue
			}
			if fd != nil && operate.Props != nil {
				// 不用加入notice，服务端逻辑会在更新后依旧更新对应值，这里的目的是更新到同步端
				// 同步到其他服务端冗余数据，会自己在更新notice时处理关联属性，不用计算
				for field, prop := range operate.Props {
					if index, ok := fd.ChessProp[field]; ok {
						chessData.Props = append(chessData.Props, chess_protocol.UpdateProp{
							Key:   byte(index),
							Value: prop,
						})
					}
				}
				continue
			}
			switch operate.Operate {
			case ChangeList:
				fallthrough
			case ChangeListTime:
				extend := structure.ExtendType(operate.Key)
				if ii, ok := fd.NoticeExtend[extend]; ok {
					//fmt.Println("nnontice", operate)
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: ii,
						Key:   operate.Index,
						Value: operate.Value,
					})
				}
				if ii, ok := fd.ChessExtend[extend]; ok {
					chessData.Extend = append(chessData.Extend, chess_protocol.UpdateExtend{
						Index: ii,
						Key:   operate.Index,
						Value: operate.Value,
					})
				}
			case RemoveDepend:
				n, pp, ii := logic.removeDepend(accountId, &resetOperateData.Data, &operate, &notice, &noticeData, fd, mapInstance, allMap)
				if n == nil {
					continue
				}
				notices = append(notices, *n)
				if ii == nil {
					continue
				}
				ps := mapInstance.Location(pp)

				logic.TransformMap(allMap, ps, ii)
			case AddDepend:
				n, pp, ii := logic.addDepend(accountId, &resetOperateData.Data, &operate, &notice, &noticeData, fd, mapInstance, allMap)
				if n == nil {
					continue
				}
				notices = append(notices, *n)
				if ii == nil {
					continue
				}
				ps := mapInstance.Location(pp)
				logic.TransformMap(allMap, ps, ii)
			}
		}
		notice.Content = noticeData
		notices = append(notices, notice)

		if fd == nil {
			goto Return
		}
		if !fd.IsChess {
			goto Return
		}
		if data.ToBool(Ignore) {
			goto Return
		}
		position := data.ToBytes(Position)
		if position == nil || len(position) == 0 {
			goto Return
		}
		var item interface{}
		// 如果是节点类型, 则发送updateNode事件
		if logic.IsNodeType(data.GetDataType()) {
			item = &chess_protocol.UpdateNode{
				Range:    logic.DataRange(data),
				DataType: byte(resetOperateData.Data.DataType),
				Id:       utils.ToBytes(resetOperateData.Data.Id),
				Data:     chessData,
			}
		} else {
			item = &chess_protocol.UpdateData{
				DataType: byte(resetOperateData.Data.DataType),
				Id:       resetOperateData.Data.Id,
				Data:     chessData,
			}
		}

		//fmt.Println("reset", resetOperateData.Data, resetOperateData.InfoKey, resetOperateData.Infos, data.ToBytes(Position))
		ps := mapInstance.Location(position)
		logic.TransformMap(allMap, ps, item)
	case DeleteOperate:
		deleteOperateData := od.inline.(*DeleteOperateData)

		fd := logic.GetFieldsDefine(deleteOperateData.DataType)
		notice := NoticeContent{
			OldAccountId: data.ToInt(logic.execute.GetDataType(AccountType)),
			NewAccountId: 0,
			Data:         *structure.NewBaseData(deleteOperateData.DataType, deleteOperateData.Id),
			Content: UpdateContent{
				Mode: DeleteUpdateMode,
			},
		}
		notices = append(notices, notice)

		// 移除所有依赖关系
		accountId := 0
		depends := data.Inherits()
		for dependKey, r := range depends {
			if r == nil {
				continue
			}
			if r.DataType == AccountType {
				accountId = data.ToInt(AccountDataType)
			}
			depend := logic.DefaultDepend(data.GetDataType(), dependKey)
			if depend == nil {
				continue
			}
			be := depend.Be

			if be.Index == -1 {
				// 非定义
				continue
			}
			if be.BeDependIsPosition {
				r.Id = utils.ToBytes(r.Id)
			} else if be.BeDependIsId {
				r.Id = utils.ToInt(r.Id)
			} else {
				r.Id = utils.ToString(r.Id)
			}

			updateData := chess_protocol.UpdatePublicData{}
			if be.BeDependIsPosition {
				updateData.ListNode = []chess_protocol.UpdateListNode{
					{Key: be.Index, Logic: false, Value: utils.ToBytes(deleteOperateData.Id)},
				}
			} else if be.BeDependIsNo {
				updateData.ListNo = []chess_protocol.UpdateListNo{
					{Key: be.Index, Logic: false, Value: utils.ToInt(deleteOperateData.Id)},
				}
			} else if be.BeDependIsId {
				updateData.ListId = []chess_protocol.UpdateListId{
					{Key: be.Index, Logic: false, Value: utils.ToString(deleteOperateData.Id)},
				}
			}
			notices = append(notices, NoticeContent{
				OldAccountId: accountId,
				NewAccountId: accountId,
				Data:         *r,
				Content: UpdateContent{
					UpdatePublicData: &updateData,
				},
			})

			if fd := logic.GetFieldsDefine(r.DataType); !fd.IsChess {
				continue
			}
			position := logic.GetPropCache(mapInstance, r, Position)
			ii := &chess_protocol.UpdateData{
				DataType: byte(r.DataType),
				Id:       r.Id,
				Data:     updateData,
			}
			ps := mapInstance.Location(utils.ToBytes(position))
			//ps := utils.ToString(location)

			logic.TransformMap(allMap, ps, ii)
		}
		if fd == nil {
			goto Return
		}
		if !fd.IsChess {
			goto Return
		}
		if data.ToBool(Ignore) {
			goto Return
		}
		item := &chess_protocol.DestroyData{
			DataType: byte(deleteOperateData.DataType),
			Id:       deleteOperateData.Id,
		}

		ps := mapInstance.Location(data.ToBytes(Position))
		logic.TransformMap(allMap, ps, item)
	case BatchUpdateOperate:
		updateOperateData := od.inline.(*UpdateOperateData)
		fd := logic.GetFieldsDefine(updateOperateData.Data.DataType)
		noticeData := UpdateContent{
			UpdatePublicData: &chess_protocol.UpdatePublicData{
				Props: []chess_protocol.UpdateProp{},
			},
		}
		chessData := chess_protocol.UpdatePublicData{
			Props: []chess_protocol.UpdateProp{},
		}
		var nextPosition []byte
		var message *chess_protocol.Message
		account := data.Inherit(AccountDataType)
		accountId := 0
		if account != nil {
			accountId = utils.ToInt(account.Id)
		}
		notice := NoticeContent{
			OldAccountId: accountId,
			NewAccountId: accountId,
			Data:         updateOperateData.Data,
		}
		flag := false
		chessFlag := false
		changeMove := false
		ignore := data.ToBool(Ignore)
		changeIgnore := false
		for _, operate := range updateOperateData.Operates {
			field := ""
			switch operate.Operate {
			case RemoveDepend:
				n, pp, ii := logic.removeDepend(accountId, &updateOperateData.Data, &operate, &notice, &noticeData, fd, mapInstance, allMap)
				if n == nil {
					continue
				}
				flag = true
				notices = append(notices, *n)
				if ii == nil {
					continue
				}
				ps := mapInstance.Location(pp)

				logic.TransformMap(allMap, ps, ii)
				chessFlag = true
			case AddDepend:
				n, pp, ii := logic.addDepend(accountId, &updateOperateData.Data, &operate, &notice, &noticeData, fd, mapInstance, allMap)
				if n == nil {
					continue
				}
				flag = true
				notices = append(notices, *n)
				if ii == nil {
					continue
				}
				ps := mapInstance.Location(pp)
				logic.TransformMap(allMap, ps, ii)
				chessFlag = true
			case ChangeInherit:
				depend := logic.DefaultDepend(updateOperateData.Data.DataType, operate.Key)
				if depend == nil {
					continue
				}
				be := depend.Be
				var r *structure.BaseData
				if be.BeDependIsPosition {
					r = structure.NewBaseData(be.BeDependType, utils.ToBytes(operate.Value))
				} else if be.BeDependIsNo {
					r = structure.NewBaseData(be.BeDependType, utils.ToInt(operate.Value))
				} else {
					r = structure.NewBaseData(be.BeDependType, utils.ToString(operate.Value))
				}
				noticeData.Dependents = append(noticeData.Dependents, &DependentItem{
					Key:    operate.Key,
					Depend: r,
				})
				noticeData.Inherit = true
			case IncrList:
				fallthrough
			case IncrFromList:
				fallthrough
			case ChangeList:
				fallthrough
			case ChangeListTime:
				if index, ok := fd.ChessExtend[structure.ExtendType(operate.Key)]; ok {
					chessFlag = true
					chessData.Extend = append(chessData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   operate.Index,
						Value: operate.Value,
					})
					//fmt.Println("list extend", updateOperateData.Data, index, operate.Index, operate.Value)
				}
				if index, ok := fd.NoticeExtend[structure.ExtendType(operate.Key)]; ok {
					flag = true
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   operate.Index,
						Value: operate.Value,
					})
					//fmt.Println("list extend", index, operate.Index, operate.Value)
				}
			case AddSet:
				if index, ok := fd.NoticeExtend[structure.ExtendType(operate.Key)]; ok {
					flag = true
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.InsertOperateExtend,
						Value: operate.Value,
					})
				}
			case RemoveSet:
				if index, ok := fd.NoticeExtend[structure.ExtendType(operate.Key)]; ok {
					flag = true
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.DeleteOperateExtend,
						Value: operate.Value,
					})
				}
			case ChangePosition:
				changeMove = true
				nextPosition = utils.ToBytes(operate.Value)
				field = Position
				//fmt.Println("update position", updateOperateData.Data, data.ToBytes(Position), nextPosition)
				fallthrough
			case ChangeIgnore:
				if field == "" {
					//fmt.Println("ignore", data.Data(), ignore, utils.ToBool(operate.Value))
					if ignore == utils.ToBool(operate.Value) {
						continue
					}
					changeIgnore = true
					ignore = utils.ToBool(operate.Value)
					data.MergeProp(Ignore, ignore)
					field = Ignore
				}
				fallthrough
			case ChangeData:
				fallthrough
			case ChangeDateTime:
				fallthrough
			case ChangeDataGreater:
				fallthrough
			case ChangeDataLesser:
				fallthrough
			case ChangeDataGreaterSync:
				fallthrough
			case ChangeDataLesserSync:
				fallthrough
			case IncrData:
				fallthrough
			case IncrDataSync:
				fallthrough
			case IncrDataGreater:
				fallthrough
			case IncrDataLesser:
				fallthrough
			case IncrDataGreaterSync:
				fallthrough
			case IncrDataLesserSync:
				field = operate.Key
				flag = true
				if fd == nil {
					noticeData.Props = append(noticeData.Props, UpdateField{
						Key:   field,
						Value: operate.Value,
					})
					continue
				}
				if ff, ok := fd.Map[field]; ok && ff.Local {
					// 只在本地更新
					updateInstance := data.Receive(ff.PropType)
					if updateInstance == nil {
						continue
					}
					updateInstance.UpdateField(field, operate.Value, noticeData.UpdatePublicData)
				} else if index, ok := fd.NoticeProp[field]; ok {
					noticeData.UpdatePublicData.Props = append(noticeData.UpdatePublicData.Props, chess_protocol.UpdateProp{
						Key:   byte(index),
						Value: operate.Value,
					})
				} else {
					noticeData.Props = append(noticeData.Props, UpdateField{
						Key:   field,
						Value: operate.Value,
					})
				}
				if index, ok := fd.ChessProp[field]; ok {
					chessFlag = true
					chessData.Props = append(chessData.Props, chess_protocol.UpdateProp{
						Key:   byte(index),
						Value: operate.Value,
					})
				}
			case AddSorted:
				fallthrough
			case AddTimeSorted:
				if index, ok := fd.NoticeExtend[structure.ExtendType(operate.Key)]; ok {
					flag = true
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.InsertOperateExtend,
						No:    operate.Index,
						Value: operate.Value,
					})
				}
				if index, ok := fd.ChessExtend[structure.ExtendType(operate.Key)]; ok {
					chessFlag = true
					chessData.Extend = append(chessData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.InsertOperateExtend,
						No:    operate.Index,
						Value: operate.Value,
					})
				}
			case RemoveSorted:
				fallthrough
			case RemoveTimeSorted:
				//operate.Value = (&structure.SortedData{Value: operate.Value, Score: operate.Index}).Bytes()
				if index, ok := fd.NoticeExtend[structure.ExtendType(operate.Key)]; ok {
					flag = true
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.DeleteOperateExtend,
						No:    operate.Index,
						Value: operate.Value,
					})
				}
				if index, ok := fd.ChessExtend[structure.ExtendType(operate.Key)]; ok {
					chessFlag = true
					chessData.Extend = append(chessData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.DeleteOperateExtend,
						No:    operate.Index,
						Value: operate.Value,
					})
				}
			case ClearTimeSorted:
				operate.Value = (&structure.SortedData{Value: operate.Value, Score: operate.Index}).Bytes()
				if index, ok := fd.NoticeExtend[structure.ExtendType(operate.Key)]; ok {
					flag = true
					noticeData.Extend = append(noticeData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.BatchDeleteOperateExtend,
						No:    operate.Index,
					})
				}
				if index, ok := fd.ChessExtend[structure.ExtendType(operate.Key)]; ok {
					chessFlag = true
					chessData.Extend = append(chessData.Extend, chess_protocol.UpdateExtend{
						Index: index,
						Key:   chess_protocol.BatchDeleteOperateExtend,
						No:    operate.Index,
					})
				}
			case ResetTimeSorted:
				operate.Value = (&structure.SortedData{Value: operate.Value, Score: operate.Index}).Bytes()
				if index, ok := fd.NoticeExtend[structure.ExtendType(operate.Key)]; ok {
					flag = true
					noticeData.Reset = append(noticeData.Reset, chess_protocol.ResetExtend{
						Index: index,
						List:  []chess_protocol.ExtendItem{},
					})
				}
				if index, ok := fd.ChessExtend[structure.ExtendType(operate.Key)]; ok {
					chessFlag = true
					chessData.Reset = append(chessData.Reset, chess_protocol.ResetExtend{
						Index: index,
						List:  []chess_protocol.ExtendItem{},
					})
				}
			case BindEvent:
				if operate.Value != nil {
					flag = true
					noticeData.Event = append(noticeData.Event, *logic.execute.GenerateEvent(utils.ToByte(operate.Value), structure.EventMode(operate.Index), utils.ToBytes(operate.Key)))
				}
			case ClearEvent:
				if operate.Value != nil {
					flag = true
					noticeData.Event = append(noticeData.Event, structure.EventData{Event: utils.ToByte(operate.Value)})
					noticeData.Mode = ClearUpdateMode
				}
			}
			if operate.Props != nil {
				// 不用加入notice，服务端逻辑会在更新后依旧更新对应值，这里的目的是更新到同步端
				// 同步到其他服务端冗余数据，会自己在更新notice时处理关联属性，不用计算
				for field, prop := range operate.Props {
					if index, ok := fd.ChessProp[field]; ok {
						chessFlag = true
						chessData.Props = append(chessData.Props, chess_protocol.UpdateProp{
							Key:   byte(index),
							Value: prop,
						})
					}
				}
			}
		}
		if updateOperateData.Message != nil {
			message = updateOperateData.Message.ToChess()
			message.Persistent = false
			message.Range = mapInstance.MessageRange(message.Event)
			//fmt.Println("update message", flag, chessFlag, changeMove, message)
		}
		if !flag && message == nil {
			goto Return
		}
		notice.Content = noticeData
		notice.Content.Message = message

		notices = append(notices, notice)

		if fd == nil || !fd.IsChess {
			goto Return
		}
		//fmt.Println("update", data.Data(), chessFlag, changeMove, changeIgnore)
		if !chessFlag && !changeMove && !changeIgnore && message == nil {
			goto Return
		}
		//ps := utils.ToString(data[Location])
		//fmt.Println("update", updateOperateData.Data, changeIgnore, ignore, changeMove)
		if changeIgnore {
			if ignore {
				pp := data.ToBytes(Position)
				if pp == nil || len(pp) == 0 {
					//fmt.Println("error update", data, updateOperateData.Data, data.Inherits(), data.GetProp(Position), changeMove, changeIgnore)
					goto Return
				}
				ps := mapInstance.Location(pp)
				// 销毁
				item := &chess_protocol.DestroyData{
					DataType: byte(updateOperateData.Data.DataType),
					Id:       updateOperateData.Data.Id,
					//Position: utils.ToBytes(positionI),
				}
				//fmt.Println("update destroy", pp, updateOperateData.Data)
				logic.TransformMap(allMap, ps, item)
			} else {
				// 提前更新
				logic.UpdateDetail(mapInstance, data, &notice.Content)

				ps, item := mapInstance.TransformLoad(updateOperateData.Data.DataType, data, message)

				//fmt.Println("update create", pp, updateOperateData.Data, data.GetProp(Position), item)
				logic.TransformMap(allMap, ps, item)
			}
		} else {
			if ignore {
				//fmt.Println("update ignore", updateOperateData.Data)
				goto Return
			}
			pp := data.ToBytes(Position)
			if pp == nil || len(pp) == 0 {
				//fmt.Println("error update", data, updateOperateData.Data, data.Inherits(), data.GetProp(Position), changeMove, changeIgnore)
				goto Return
			}
			ps := mapInstance.Location(pp)
			chessData.Message = message
			//fmt.Println("update message", message)
			if changeMove {
				mm := &chess_protocol.MoveData{
					DataType: byte(updateOperateData.Data.DataType),
					Id:       updateOperateData.Data.Id,
					Current:  nextPosition,
					Data:     chessData,
					Position: pp,
				}
				//fmt.Println("move", pp, nextPosition, updateOperateData.Data, chessData)
				logic.TransformMap(allMap, ps, mm)
			} else if chessFlag {
				item := &chess_protocol.UpdateData{
					DataType: byte(updateOperateData.Data.DataType),
					Id:       updateOperateData.Data.Id,
					Data:     chessData,
				}
				//fmt.Println("update chess", pp, item.Data)
				logic.TransformMap(allMap, ps, item)
			} else if message != nil {
				logic.TransformMap(allMap, ps, &chess_protocol.SendMessage{
					DataType: utils.ToByte(updateOperateData.Data.DataType),
					Id:       updateOperateData.Data.Id,
					Message:  message,
				})
			}
		}
	case EventOperate:
		eventOperateData := od.inline.(*EventOperateData)

		notice := NoticeContent{
			OldAccountId: 0,
			NewAccountId: 0,
			Data:         eventOperateData.Data,
			Content: UpdateContent{
				Mode:  0,
				Event: []structure.EventData{*eventOperateData.eventData},
			},
		}

		notices = append(notices, notice)
	}
Return:
	return allMap, notices
}

func (logic *LogicExecute) SyncToOrbit(mapInstance MapProxy, allMap map[string][]interface{}, t int64) {
	var err error
	for ps, v := range allMap {
		d := &chess_protocol.BlockData{
			MapNoId: mapInstance.GetMapNoId(),
			Mode:    mapInstance.GetMode(),
			Sub:     ps,
			Detail:  []chess_protocol.DetailData{},
			Time:    t,
		}
		var t chess_protocol.DetailType
		for _, vv := range v {
			c := []byte{}
			switch vvv := vv.(type) {
			case *chess_protocol.SingleData:
				t = chess_protocol.CreateDataDetail
				//fmt.Println("create data", vvv.DataType, vvv.Id, vvv.Data)
				c, err = vvv.MarshalMsg(c)
				if err != nil {
					fmt.Println("sync createdata", err)
				}
			case *chess_protocol.UpdateData:
				t = chess_protocol.UpdateDataDetail
				c, err = vvv.MarshalMsg(c)
				if err != nil {
					fmt.Println("sync updatedata", err)
				}
			case *chess_protocol.MoveData:
				t = chess_protocol.MoveDataDetail
				c, err = vvv.MarshalMsg(c)
				if err != nil {
					fmt.Println("sync movedata", err)
				}
			case *chess_protocol.DestroyData:
				t = chess_protocol.DestroyDataDetail
				c, err = vvv.MarshalMsg(c)
				if err != nil {
					fmt.Println("sync destroydata", err)
				}
			//case *chess_protocol.Data:
			//	t = chess_protocol.CreateNodeDetail
			//	c, err = vvv.MarshalMsg(c)
			//	if err != nil {
			//		fmt.Println("sync createnode", err)
			//	}
			case *chess_protocol.UpdateNode:
				t = chess_protocol.UpdateNodeDetail
				c, err = vvv.MarshalMsg(c)
				if err != nil {
					fmt.Println("sync updatenode", err)
				}
			case *chess_protocol.SendMessage:
				t = chess_protocol.SendMessageDetail
				c, err = vvv.MarshalMsg(c)
				if err != nil {
					fmt.Println("sync sendmessage", err)
				}
			}
			d.Detail = append(d.Detail, chess_protocol.DetailData{
				Type:    t,
				Content: c,
			})
		}
		//fmt.Println("send orbit receive")
		if err := logic.agent.Request("orbit").Hash().Do("chess/receive", d); err != nil {
			fmt.Println("orbit chess receive", err)
		}
	}
}

func (logic *LogicExecute) Operate(conn structure.SafeConn, mapInstance *MapInstance, from structure.Data, target structure.Data, operates []OperateData, operateMessage *OperateMessage, t int64) bool {
	if operates == nil && operateMessage == nil {
		return true
	}
	allMap := map[string][]interface{}{}
	var inlineFrom structure.Data
	list := []NoticeContent{}
	var fromInfo PropsInstance
	if from != nil && from.Exist() {
		fromInfo = logic.GetDetailCache(mapInstance, from)
	}
	//fmt.Println("operate", from, target, operates, operateMessage)
	conn.Connect()
	if operates != nil {
		conn.Begin()
		slot := serialize.GetSlot()
		for _, od := range operates {
			inlineFrom = from
			var info PropsInstance
			slot.Clear()
			switch od.Operate {
			case CreateOperate:
				var createOperateData CreateOperateData
				if od.inline == nil {
					_ = slot.Set(&createOperateData)
					_ = slot.Unmarshal(od.Data)
					od.inline = &createOperateData
				} else {
					createOperateData = *od.inline.(*CreateOperateData)
				}

				if createOperateData.From != nil {
					inlineFrom = createOperateData.From
				}
				mapInstance.OnCreateHandle(&createOperateData)
				data := map[string]interface{}{
					Id:       createOperateData.Data.Id,
					Position: createOperateData.Position,
				}
				fd := logic.GetFieldsDefine(createOperateData.Data.DataType)
				if fd != nil && fd.IsChess {
					if fd.IsId {
						createOperateData.Data.Id = utils.ToString(createOperateData.Data.Id)
					} else if fd.IsNo {
						createOperateData.Data.Id = utils.ToInt(createOperateData.Data.Id)
					} else if fd.IsPosition {
						createOperateData.Data.Id = utils.ToBytes(createOperateData.Data.Id)
					}
				}
				createOperateData.updateOperates = make([]UpdateOperateContent, len(createOperateData.Infos))
				for index, info := range createOperateData.Infos {
					if len(createOperateData.InfoKey) == index {
						break
					}
					operate := UpdateOperateContent{
						Key:       createOperateData.InfoKey[index],
						Value:     info,
						SyncValue: info,
						Operate:   ChangeData,
					}
					persistence := true
					if fd != nil {
						if ff, ok := fd.Map[operate.Key]; ok {
							persistence = ff.Persistence
						} else {
							persistence = logic.IsPersistence(operate.Key)
						}
					}

					//if operate.Key == Key {
					//	fmt.Println("operate create", createOperateData.Data, operate.Key, operate.Value, logic.IsPersistence(operate.Key), persistence)
					//}
					if logic.OnOperateBefore(mapInstance, nil, fd, inlineFrom, &operate) || persistence {
						data[operate.Key] = operate.Value
					}
					// 保存为同步值
					tmp := operate.Value
					operate.Value = operate.SyncValue
					operate.SyncValue = tmp
					createOperateData.Infos[index] = operate.Value
					createOperateData.updateOperates[index] = operate
				}
				if logic.NeedMapNo(createOperateData.Data.DataType) {
					data[MapNoId] = mapInstance.MapNoId
				}
				info = NewPropInstance(logic, fd, &createOperateData.Data, data)
				mapInstance.OnCreateBefore(fromInfo, info)
				for index := range createOperateData.updateOperates {
					logic.OnOperateAfter(mapInstance, info, fd, inlineFrom, &createOperateData.updateOperates[index])
				}

				idString, _ := logic.AdditionMapId(mapInstance.MapNoId, createOperateData.Data.DataType, createOperateData.Data.Id)
				dd := structure.NewBaseData(createOperateData.Data.DataType, idString)
				logic.execute.Create(conn, dd, data)

				for index, value := range createOperateData.Extends {
					if len(createOperateData.ExtendKey) == index {
						break
					}
					extend := structure.ExtendType(createOperateData.ExtendKey[index])
					mode := logic.GetExtendMode(extend)
					switch mode {
					case structure.ListExtendMode:
						e := make([]interface{}, len(value))
						for index, item := range value {
							e[index] = item.Value
						}
						logic.execute.CreateListExtend(conn, dd, extend, e)
					case structure.SetExtendMode:
						e := make([]interface{}, len(value))
						for index, item := range value {
							e[index] = item.Value
						}
						logic.execute.AddSetExtend(conn, dd, extend, e)
					case structure.SortedExtendMode:
						e := make([]*structure.SortedData, len(value))
						for index, item := range value {
							e[index] = &structure.SortedData{
								Score: item.No,
								Value: item.Value,
							}
						}
						logic.execute.AddSortedExtend(conn, dd, extend, e)
					}
				}
				if createOperateData.Dependents != nil {
					for _, item := range createOperateData.Dependents {
						r := item.Depend
						if r.DataType == AccountType {
							createOperateData.accountId = utils.ToInt(r.Id)
						}
						createOperateData.InfoKey = append(createOperateData.InfoKey, item.Key)
						createOperateData.Infos = append(createOperateData.Infos, r.Id)
						depend := logic.DefaultDepend(dd.DataType, item.Key)
						be := depend.Be
						idString, _ := logic.AdditionMapId(mapInstance.MapNoId, be.BeDependType, item.Depend.Id)
						//fmt.Println("create dependent", createOperateData.Data, r, depend, item.Depend, idString)
						tmp := item.Depend.Id
						item.Depend.Id = idString
						logic.execute.AddDepend(conn, item.Depend, dd, be.BeDepend, be.Depend)
						if be.BeDependIsPosition {
							item.Depend.Id = utils.ToBytes(tmp)
						} else if be.BeDependIsNo {
							item.Depend.Id = utils.ToInt(tmp)
						} else if be.BeDependIsId {
							item.Depend.Id = utils.ToString(tmp)
						} else {
							item.Depend.Id = tmp
						}
						operate := UpdateOperateContent{
							Operate: AddDepend,
							Key:     item.Key,
							Value:   item.Depend.Id,
						}
						createOperateData.updateOperates = append(createOperateData.updateOperates, operate)
					}
				}
				od.inline = &createOperateData
				od.IdString = idString
				//fmt.Println("create", createOperateData.Data, info, createOperateData.InfoKey, createOperateData.Infos)
			case ResetOperate:
				var resetOperateData ResetOperateData
				if od.inline == nil {
					_ = slot.Set(&resetOperateData)
					_ = slot.Unmarshal(od.Data)
					od.inline = &resetOperateData
				} else {
					resetOperateData = *od.inline.(*ResetOperateData)
				}
				if resetOperateData.From != nil {
					inlineFrom = resetOperateData.From
				}
				fd := logic.GetFieldsDefine(resetOperateData.Data.DataType)
				if fd != nil && fd.IsChess {
					if fd.IsId {
						resetOperateData.Data.Id = utils.ToString(resetOperateData.Data.Id)
					} else if fd.IsNo {
						resetOperateData.Data.Id = utils.ToInt(resetOperateData.Data.Id)
					} else if fd.IsPosition {
						resetOperateData.Data.Id = utils.ToBytes(resetOperateData.Data.Id)
					}
				}
				data := map[string]interface{}{}
				//fmt.Println("reset", resetOperateData)
				info = logic.GetDetailCache(mapInstance, &resetOperateData.Data)
				if info == nil {
					fmt.Println("reset empty", resetOperateData.Data, info, resetOperateData.InfoKey, resetOperateData.Infos)
				}
				//fmt.Println("reset", resetOperateData, info.ToBytes(Position))
				resetOperateData.updateOperates = make([]UpdateOperateContent, len(resetOperateData.Infos))
				for index, value := range resetOperateData.Infos {
					if len(resetOperateData.InfoKey) == index {
						break
					}
					operate := UpdateOperateContent{
						Key:       resetOperateData.InfoKey[index],
						Value:     value,
						SyncValue: value,
						Operate:   ChangeData,
					}
					persistence := true
					if fd != nil {
						if ff, ok := fd.Map[operate.Key]; ok {
							persistence = ff.Persistence
						} else {
							persistence = logic.IsPersistence(operate.Key)
						}
					}

					//fmt.Println("operate reset", info.ToString(Key), operate.Key, logic.IsPersistence(operate.Key), persistence)
					if logic.OnOperateBefore(mapInstance, info, fd, inlineFrom, &operate) || persistence {
						data[operate.Key] = operate.Value
					}

					// 保存为同步值
					tmp := operate.Value
					operate.Value = operate.SyncValue
					operate.SyncValue = tmp
					resetOperateData.Infos[index] = operate.Value
					resetOperateData.updateOperates[index] = operate
				}
				if logic.NeedMapNo(resetOperateData.Data.DataType) {
					data[MapNoId] = mapInstance.MapNoId
				}

				mapInstance.OnResetBefore(fromInfo, info)
				for index := range resetOperateData.updateOperates {
					logic.OnOperateAfter(mapInstance, info, fd, inlineFrom, &resetOperateData.updateOperates[index])
				}

				idString, _ := logic.AdditionMapId(mapInstance.MapNoId, resetOperateData.Data.DataType, resetOperateData.Data.Id)
				dd := structure.NewBaseData(resetOperateData.Data.DataType, idString)
				logic.execute.Update(conn, dd, data)
				info.MergeProps(data)

				if resetOperateData.Dependents != nil {
					for _, item := range resetOperateData.Dependents {
						r := item.Depend
						resetOperateData.InfoKey = append(resetOperateData.InfoKey, item.Key)
						resetOperateData.Infos = append(resetOperateData.Infos, r.Id)
						depend := logic.DefaultDepend(dd.DataType, item.Key)
						be := depend.Be
						idString, _ := logic.AdditionMapId(mapInstance.MapNoId, be.BeDependType, item.Depend.Id)
						//fmt.Println("create dependent", createOperateData.Data, r, idString, need)
						tmp := item.Depend.Id
						inherit := info.Inherit(item.Key)
						if inherit == nil {
							item.Depend.Id = idString
							logic.execute.AddDepend(conn, item.Depend, dd, be.BeDepend, be.Depend)
						} else if item.Depend.Id == inherit.Id {
							continue
						} else {
							tmpOld := inherit.Id
							idStringOld, needOld := logic.AdditionMapId(mapInstance.MapNoId, be.BeDependType, inherit.Id)
							inherit.Id = idStringOld
							logic.execute.RemoveDepend(conn, inherit, dd, be.BeDepend, be.Depend)
							if needOld {
								inherit.Id = utils.ToBytes(tmpOld)
							} else {
								inherit.Id = tmpOld
							}
							operate := UpdateOperateContent{
								Operate: RemoveDepend,
								Key:     item.Key,
								Value:   inherit.Id,
							}
							resetOperateData.updateOperates = append(resetOperateData.updateOperates, operate)
							if item.Depend.Id == nil {
								continue
							}
						}
						if be.BeDependIsPosition {
							item.Depend.Id = utils.ToBytes(tmp)
						} else if be.BeDependIsNo {
							item.Depend.Id = utils.ToInt(tmp)
						} else if be.BeDependIsId {
							item.Depend.Id = utils.ToString(tmp)
						} else {
							item.Depend.Id = tmp
						}
						operate := UpdateOperateContent{
							Operate: AddDepend,
							Key:     item.Key,
							Value:   item.Depend.Id,
						}
						resetOperateData.updateOperates = append(resetOperateData.updateOperates, operate)
					}
				}
				od.inline = &resetOperateData
				od.IdString = idString
				//instance.OnResetAfter(conn, info)
			case DeleteOperate:
				var deleteOperateData DeleteOperateData
				if od.inline == nil {
					_ = slot.Set(&deleteOperateData)
					_ = slot.Unmarshal(od.Data)
					od.inline = &deleteOperateData
				} else {
					deleteOperateData = *od.inline.(*DeleteOperateData)
				}
				fd := logic.GetFieldsDefine(deleteOperateData.DataType)
				if deleteOperateData.From != nil {
					inlineFrom = deleteOperateData.From
				}
				if fd != nil && fd.IsChess {
					if fd.IsId {
						deleteOperateData.Id = utils.ToString(deleteOperateData.Id)
					} else if fd.IsNo {
						deleteOperateData.Id = utils.ToInt(deleteOperateData.Id)
					} else if fd.IsPosition {
						deleteOperateData.Id = utils.ToBytes(deleteOperateData.Id)
					}
				}
				da := structure.NewBaseData(deleteOperateData.DataType, deleteOperateData.Id)
				info = logic.GetDetailCache(mapInstance, da)
				if info == nil {
					// 已经删除
					fmt.Println("delete miss", da)
					continue
				}

				mapInstance.OnDestroyBefore(fromInfo, info)

				idString, _ := logic.AdditionMapId(mapInstance.MapNoId, deleteOperateData.DataType, deleteOperateData.Id)
				dd := structure.NewBaseData(deleteOperateData.DataType, idString)

				fmt.Println("delete", info.Data(), dd)
				for _, depend := range fd.DependMap {
					inherit := info.Inherit(depend.Key)
					if inherit == nil {
						continue
					}
					idString, need := logic.AdditionMapId(mapInstance.MapNoId, depend.Be.BeDependType, inherit.Id)
					tmp := inherit.Id
					if need {
						inherit.Id = idString
					}
					fmt.Println("delete depend", info.Data(), dd, depend)
					logic.execute.RemoveDepend(conn, inherit, dd, depend.Be.BeDepend, depend.Be.Depend)
					inherit.Id = tmp
				}
				for _, beDepend := range fd.BeDepends {
					logic.execute.ClearDepend(conn, dd, beDepend.BeDepend, beDepend.DependType, beDepend.Depend)
				}
				for _, extend := range fd.NoticeExtendMap {
					if extend.AutoClean {
						logic.execute.DeleteExtend(conn, dd, extend.Extend)
					}
				}
				//fmt.Println("delete", dd)
				logic.execute.Delete(conn, dd)
				od.inline = &deleteOperateData
				od.IdString = idString
			case BatchUpdateOperate:
				var updateOperateData UpdateOperateData
				if od.inline == nil {
					_ = slot.Set(&updateOperateData)
					if err := slot.Unmarshal(od.Data); err != nil {
						fmt.Println("batch update", err, od.Data, operates, operateMessage)
					}
					od.inline = &updateOperateData
				} else {
					updateOperateData = *od.inline.(*UpdateOperateData)
				}
				if updateOperateData.From != nil {
					inlineFrom = updateOperateData.From
				}
				//fmt.Println(updateOperateData)
				if !logic.checkList(mapInstance, updateOperateData.Checks) {
					continue
				}
				// 用来关联处理，一次完成复合操作
				if updateOperateData.Data.Id == nil {
					updateOperateData.Data = *structure.NewBaseDataFrom(target)
				}
				idString, _ := logic.AdditionMapId(mapInstance.MapNoId, updateOperateData.Data.DataType, updateOperateData.Data.Id)
				info = logic.GetDetailCache(mapInstance, &updateOperateData.Data)
				//fmt.Println(updateOperateData, info)
				if info == nil {
					fmt.Println("operate empty", updateOperateData.Data, updateOperateData.Operates)
					continue
				}
				fd := logic.GetFieldsDefine(updateOperateData.Data.DataType)
				if fd != nil && fd.IsChess {
					if fd.IsId {
						updateOperateData.Data.Id = utils.ToString(updateOperateData.Data.Id)
					} else if fd.IsNo {
						updateOperateData.Data.Id = utils.ToInt(updateOperateData.Data.Id)
					} else if fd.IsPosition {
						updateOperateData.Data.Id = utils.ToBytes(updateOperateData.Data.Id)
					}
				}
				var pass interface{}
				for i, _ := range updateOperateData.Operates {
					operate := &updateOperateData.Operates[i]
					operate.PassValue = pass
					// 调整参数
					switch operate.Operate {
					case ChangeDateTime:
						operate.Value = logic.FormatTime(utils.ToInt64(operate.Value))
					case ChangeListTime:
						operate.Value = logic.FormatSecond(utils.ToInt(operate.Value))
					case AddTimeSorted:
						operate.Index = logic.FormatSecond(operate.Index)
					case ClearTimeSorted:
						operate.Index = logic.FormatSecond(operate.Index)
					case ChangePosition:
						operate.Key = Position
					case ChangeIgnore:
						operate.Key = Ignore
						//case AddDepend:
						//	fallthrough
						//case RemoveDepend:
						//	fallthrough
						//case ChangeInherit:
						//	depend := logic.DefaultDepend(info.GetDataType(), operate.Key)
						//	operate.Index = int(depend.BeDependType)
					}
					operate.SyncValue = operate.Value
					persistence := true
					if fd != nil {
						if ff, ok := fd.Map[operate.Key]; ok {
							persistence = ff.Persistence
						} else {
							persistence = logic.IsPersistence(operate.Key)
						}
					}
					//fmt.Println("persistence", operate.Key, persistence)
					if logic.OnOperateBefore(mapInstance, info, fd, inlineFrom, operate) || persistence {
						logic.UpdateOperate(conn, mapInstance.MapNoId, inlineFrom, info, idString, operate)
					}
					tmp := operate.Value
					operate.Value = operate.SyncValue
					operate.SyncValue = tmp
					pass = operate.PassValue
					logic.OnOperateAfter(mapInstance, info, fd, inlineFrom, operate)
				}
				od.IdString = idString
			case EventOperate:
				var eventOperateData EventOperateData
				if od.inline == nil {
					_ = slot.Set(&eventOperateData)
					_ = slot.Unmarshal(od.Data)
					od.inline = &eventOperateData
				} else {
					eventOperateData = *od.inline.(*EventOperateData)
				}
				fd := logic.GetFieldsDefine(eventOperateData.Data.DataType)
				if fd != nil && fd.IsChess {
					if fd.IsId {
						eventOperateData.Data.Id = utils.ToString(eventOperateData.Data.Id)
					} else if fd.IsNo {
						eventOperateData.Data.Id = utils.ToInt(eventOperateData.Data.Id)
					} else if fd.IsPosition {
						eventOperateData.Data.Id = utils.ToBytes(eventOperateData.Data.Id)
					}
				}
				idString, _ := logic.AdditionMapId(mapInstance.MapNoId, eventOperateData.Data.GetDataType(), eventOperateData.Data.GetId())
				eventData := logic.execute.BindEvent(conn, structure.NewBaseData(eventOperateData.Data.GetDataType(), idString), eventOperateData.Event, eventOperateData.Mode, eventOperateData.Content)
				eventOperateData.eventData = eventData
			}

			if err := conn.Commit(); err != nil {
				debug.PrintStack()
				fmt.Println("operate", err)
			}
			allMap, list = logic.transformOperate(mapInstance, od, info, allMap, list)
			slot.Clear()
		}
		slot.Release()
	}

	// 添加消息
	if operateMessage != nil {
		var position []byte
		//fmt.Println("send message", position, operateMessage.Message, target)
		if operateMessage.Data == nil {
			operateMessage.Data = structure.NewBaseDataFrom(target)
		}

		data := logic.GetDetailCache(mapInstance, operateMessage.Data)
		if data != nil {
			if operateMessage.Position == nil || len(operateMessage.Position) == 0 {
				position = utils.ToBytes(data.ToBytes(Position))
			} else {
				position = operateMessage.Position
			}
			//fmt.Println("operate message", data.ToBool(Ignore), operateMessage.Data, operateMessage.Message.Event, operateMessage.Position, t, logic.CurrentTime())

			message := operateMessage.Message.ToChess()
			message.Range = mapInstance.MessageRange(message.Event)
			message.Persistent = operateMessage.Persistent
			if !data.ToBool(Ignore) {
				//fmt.Println("send message", position, operateMessage.Data, operateMessage.Message)

				location := mapInstance.Location(position)
				logic.TransformMap(allMap, location, &chess_protocol.SendMessage{
					DataType: utils.ToByte(operateMessage.Data.DataType),
					Id:       operateMessage.Data.Id,
					Message:  message,
				})
			} else {
				if operateMessage.Message.Event == 1 {
					//fmt.Println("send message", position, operateMessage.Data, operateMessage.Message, data.ToBool(Ignore))
				}
			}

			accountId := data.ToInt(AccountDataType)
			list = append(list, NoticeContent{
				OldAccountId: accountId,
				NewAccountId: accountId,
				Data:         *operateMessage.Data,
				Content: UpdateContent{
					UpdatePublicData: &chess_protocol.UpdatePublicData{Message: message},
				},
			})
		}

	}
	if len(list) > 0 {
		logic.Notice.OnUpdate(&UpdateNotice{
			MapNoId: mapInstance.MapNoId,
			List:    list,
		})
	}
	logic.SyncToOrbit(mapInstance, allMap, t)
	return true
}

func (logic *LogicExecute) checkList(mapInstance MapProxy, checks [][]CheckData) bool {
	if checks == nil {
		return true
	}
	for _, or := range checks {
		if logic.checkOne(mapInstance, or) {
			return true
		}
	}
	return false
}

func (logic *LogicExecute) checkOne(mapInstance MapProxy, or []CheckData) bool {
	currentTime := logic.CurrentTime()
	for _, cc := range or {
		//idString := logic.AdditionMapId(mapNoId, cc.Data.DataType, cc.Data.Id)
		//dd := structure.NewBaseData(cc.Data.DataType, idString)
		i := logic.GetDetailCache(mapInstance, &cc.Data)
		//extends := make(map[structure.ExtendType][]interface{})
		for _, check := range cc.Checks {
			switch check.Check {
			case ExistCheck:
				if i == nil {
					return false
				}
			case DataCheck:
				if i == nil {
					return false
				}
				if i.ToString(check.Key) != utils.ToString(check.Value) {
					return false
				}
			case EqualCheck:
				if i == nil {
					return false
				}
				if i.ToInt(check.Key) != utils.ToInt(check.Value) {
					return false
				}
			case GreaterCheck:
				if i == nil {
					return false
				}
				if i.ToInt(check.Key) < utils.ToInt(check.Value) {
					return false
				}
			case LessCheck:
				if i == nil {
					return false
				}
				if i.ToInt(check.Key) > utils.ToInt(check.Value) {
					return false
				}
			case PositionEqualCheck:
				if i == nil {
					return false
				}
				source := i.ToBytes(check.Key)
				target := utils.ToBytes(check.Value)
				if source == nil || len(source) == 0 {
					return false
				}
				if !bytes.Equal(source, target) {
					return false
				}
			case PositionUnEqualCheck:
				if i == nil {
					return false
				}
				source := i.ToBytes(check.Key)
				target := utils.ToBytes(check.Value)
				if source == nil || len(source) == 0 {
					return false
				}
				if bytes.Equal(source, target) {
					return false
				}
			case SustainTimeExistCheck:
				if i == nil {
					return false
				}
				source := NewSustainBy(i.GetProp(check.Key))
				if source == nil {
					return false
				}
				delay := utils.ToInt64(check.Value)
				//fmt.Println("sustain exist", delay, source.Time, currentTime, source.Time+delay >= currentTime)
				if source.Time+delay < currentTime {
					return false
				}
				if check.Index > 0 && check.Index != source.Type {
					return false
				}
			case SustainTimeNoExistCheck:
				if i == nil {
					return false
				}
				source := NewSustainBy(i.GetProp(check.Key))
				if source == nil {
					continue
				}
				delay := utils.ToInt64(check.Value)
				if source.Time+delay > currentTime {
					return false
				}
				if check.Index > 0 && check.Index == source.Type {
					return false
				}
			}
		}
	}
	return true
}

func (logic *LogicExecute) UpdateOperate(conn structure.SafeConn, mapNoId string, from structure.Data, target PropsInstance, idString string, op *UpdateOperateContent) {
	//HINCRBY
	//fmt.Println(target, idString, op.Operate)
	dd := structure.NewBaseData(target.GetDataType(), idString)
	switch op.Operate {
	case ChangeData:
		//fmt.Println("change", target, op)
		if op.Value == nil {
			logic.execute.DelProp(conn, dd, op.Key)
		} else {
			logic.execute.SetProp(conn, dd, op.Key, op.Value)
		}
	case ChangeDataSync:
		// syncValue = new
		// value = old
		op.SyncValue = op.Value
		op.Value = target.ToInt(op.Key)
		logic.execute.SetProp(conn, dd, op.Key, op.Value)
	case ChangeDateTime:
		logic.execute.SetProp(conn, dd, op.Key, op.Value)
	case ChangePosition:
		logic.execute.SetProp(conn, dd, Position, utils.ToBytes(op.Value))
		//location := utils.ToString(info[Location])
		//if new, ok := logic.UpdateLocation(position, location); ok {
		//	op.Key = new
		//	logic.Execute.SetProp(conn, dd, Location, new)
		//}
	case ChangeIgnore:
		logic.execute.SetProp(conn, dd, Ignore, utils.ToBool(op.Value))
	case ChangeInherit:
		logic.execute.SetProp(conn, dd, op.Key, op.Value)
	case ChangeDataGreater:
		value := utils.ToInt(op.Value)
		vv := target.ToInt(op.Key)
		if value > vv {
			logic.execute.SetProp(conn, dd, op.Key, value)
		}
		//logic.execute.SetPropGreater(conn, dd, op.Key, utils.ToInt(op.Value))
	case ChangeDataLesser:
		value := utils.ToInt(op.Value)
		vv := target.ToInt(op.Key)
		if value < vv {
			logic.execute.SetProp(conn, dd, op.Key, value)
		}
		//logic.execute.SetPropLesser(conn, dd, op.Key, utils.ToInt(op.Value))
	case ChangeDataGreaterSync:
		value := utils.ToInt(op.Value)
		vv := target.ToInt(op.Key)
		if value > vv {
			op.SyncValue = value
			op.Value = vv
			logic.execute.SetProp(conn, dd, op.Key, value)
		} else {
			op.SyncValue = vv
			op.Value = vv
		}
		//op.SyncValue, op.Value = logic.execute.SetPropGreaterSync(conn, dd, op.Key, value)
	case ChangeDataLesserSync:
		value := utils.ToInt(op.Value)
		vv := target.ToInt(op.Key)
		if value < vv {
			op.SyncValue = value
			op.Value = vv
			logic.execute.SetProp(conn, dd, op.Key, op.Value)
		} else {
			op.SyncValue = vv
			op.Value = vv
		}
		//op.SyncValue, op.Value = logic.execute.SetPropLesserSync(conn, dd, op.Key, value)
	case IncrData:
		logic.execute.IncrProp(conn, dd, op.Key, utils.ToInt(op.Value))
	case IncrDataSync:
		value := utils.ToInt(op.Value)
		vv := target.ToInt(op.Key)
		op.SyncValue = vv + value
		op.Value = value
		target.MergeProp(op.Key, op.SyncValue)
		logic.execute.SetProp(conn, dd, op.Key, op.SyncValue)
		//logic.execute.IncrProp(conn, dd, op.Key, value)
	case IncrDataGreater:
		value := utils.ToInt(op.Value)
		f := utils.ToInt(op.Index)
		vv := target.ToInt(op.Key)
		if f > vv {
			logic.execute.SetProp(conn, dd, op.Key, vv+value)
		}
		//logic.execute.IncrPropGreater(conn, dd, op.Key, utils.ToInt(op.Value), utils.ToInt(op.Index))
	case IncrDataLesser:
		value := utils.ToInt(op.Value)
		f := utils.ToInt(op.Index)
		vv := target.ToInt(op.Key)
		if f < vv {
			logic.execute.SetProp(conn, dd, op.Key, vv+value)
		}
		//logic.execute.IncrPropLesser(conn, dd, op.Key, utils.ToInt(op.Value), utils.ToInt(op.Index))
	case IncrDataGreaterSync:
		value := utils.ToInt(op.Value)
		f := utils.ToInt(op.Index)
		vv := target.ToInt(op.Key)
		if vv+value > f {
			op.SyncValue = vv + value
			op.Value = vv
			logic.execute.SetProp(conn, dd, op.Key, vv+value)
		} else {
			op.SyncValue = f
		}
		fmt.Println("greater", value, f, vv, op.SyncValue, op.Value)
		//op.SyncValue = logic.execute.IncrPropGreaterSync(conn, dd, op.Key, utils.ToInt(op.Value), utils.ToInt(op.Index))
		//fmt.Println("update", dd, op.Key, op.Value)
	case IncrDataLesserSync:
		value := utils.ToInt(op.Value)
		f := utils.ToInt(op.Index)
		vv := target.ToInt(op.Key)
		if vv+value < f {
			op.SyncValue = vv + value
			op.Value = vv
			logic.execute.SetProp(conn, dd, op.Key, vv+value)
		} else {
			op.SyncValue = f
		}
		op.SyncValue = logic.execute.IncrPropLesserSync(conn, dd, op.Key, utils.ToInt(op.Value), utils.ToInt(op.Index))
	case ChangeList:
		logic.execute.UpdateListExtend(conn, dd, structure.ExtendType(op.Key), []structure.UpdateExtend{{Index: op.Index, Value: op.Value}})
	case ChangeListTime:
		logic.execute.UpdateListExtend(conn, dd, structure.ExtendType(op.Key), []structure.UpdateExtend{{Index: op.Index, Value: op.SyncValue}})
	case IncrList:
		logic.execute.IncrListExtend(conn, dd, structure.ExtendType(op.Key), op.Index, utils.ToInt(op.Value))
	case IncrFromList:
		logic.execute.IncrFromListExtend(conn, dd, structure.ExtendType(op.Key), op.Index, utils.ToInt(op.Value))
	case AddSet:
		logic.execute.AddSetExtend(conn, dd, structure.ExtendType(op.Key), []interface{}{op.Value})
	case RemoveSet:
		logic.execute.RemoveSetExtend(conn, dd, structure.ExtendType(op.Key), []interface{}{op.Value})
	case AddSorted:
		logic.execute.AddSortedExtend(conn, dd, structure.ExtendType(op.Key), []*structure.SortedData{{Score: op.Index, Value: op.Value}})
	case RemoveSorted:
		logic.execute.RemoveSortedExtend(conn, dd, structure.ExtendType(op.Key), []interface{}{op.Value})
	case AddTimeSorted:
		op.Index = logic.FormatSecond(op.Index)
		logic.execute.AddSortedExtend(conn, dd, structure.ExtendType(op.Key), []*structure.SortedData{{Score: op.Index, Value: op.Value}})
	case RemoveTimeSorted:
		logic.execute.RemoveSortedExtend(conn, dd, structure.ExtendType(op.Key), []interface{}{op.Value})
	case ClearTimeSorted:
		// 清除过期的timesorted数据
		logic.execute.ClearSortedExtend(conn, dd, structure.ExtendType(op.Key), 0, utils.ToInt(op.Index))
	case ResetTimeSorted:
		// 删除所有timesorted数据
		logic.execute.ResetSortedExtend(conn, dd, structure.ExtendType(op.Key), nil)
	case AddTask:
		logic.execute.AddTask(conn, mapNoId, from, structure.TaskEvent(op.Index), utils.ToBytes(op.Key), op.Time, utils.ToInterfaceSlice(op.Value), nil)
	case PushSchedule:
		info := logic.execute.GenerateSchedule(mapNoId, from, target, op.Key, logic.FormatTime(op.Time), structure.ScheduleLogic(op.Index), utils.ToBytes(op.Value), nil, 0)
		logic.execute.PushSchedule(conn, info)
	case ResetSchedule:
		logic.execute.ResetSchedule(conn, mapNoId, target, op.Key, logic.FormatTime(utils.ToInt64(op.Value)), op.Index)
	case ChangeParamSchedule:
		logic.execute.ChangeParamSchedule(conn, mapNoId, target, op.Key, utils.ToInterfaceSlice(op.Value))
	case HoldSchedule:
		logic.execute.HoldSchedule(conn, mapNoId, target, op.Key, utils.ToBytes(op.Value))
	case RemoveSchedule:
		//fmt.Println("remove schedule", target, op.Key)
		logic.execute.RemoveSchedule(conn, mapNoId, target, op.Key)
	case BindEvent:
		//fmt.Println("bindevent", op)
		logic.execute.BindEvent(conn, dd, utils.ToByte(op.Value), structure.EventMode(op.Index), utils.ToBytes(op.Key))
	//case LinkEvent:
	//	eventProp := logic.GetEventProp(SystemEvent(utils.ToByte(op.Index)))
	//	logic.Execute.SetProp(conn, dd, eventProp, utils.ToByte(op.Value))
	case ClearEvent:
		//fmt.Println("clearevent", op)
		logic.execute.ClearEvent(conn, dd, utils.ToByte(op.Value))
	//case UnLinkEvent:
	//	eventProp := logic.GetEventProp(SystemEvent(utils.ToByte(op.Index)))
	//	logic.Execute.SetProp(conn, dd, eventProp, 0)
	//case UpdateNode:
	//	logic.GetMap(mapNoId).UpdateNode(utils.ToBytes(op.Value), op.Index, utils.ToByte(op.Key))
	//case UpdateFixed:
	//	logic.GetMap(mapNoId).UpdateFixed(utils.ToBytesSlice(op.Value), op.Index, utils.ToByte(op.Key), target.GetItem())
	//case UpdateSeat:
	//	var extend serialize.IStruct
	//	if op.Value != nil {
	//		extend = op.Value.(serialize.IStruct)
	//	}
	//	logic.GetMap(mapNoId).MoveSeat(target.GetItem(), utils.ToBytes(op.Key), nil, utils.ToInt64(op.Time), op.Index, extend)
	case AddDepend:
		depend := logic.DefaultDepend(dd.DataType, op.Key)
		if depend == nil {
			return
		}
		be := depend.Be
		valueString, _ := logic.AdditionMapId(mapNoId, be.BeDependType, op.Value)
		logic.execute.AddDepend(conn, structure.NewBaseData(be.BeDependType, valueString), dd, be.BeDepend, be.Depend)
	case RemoveDepend:
		depend := logic.DefaultDepend(dd.DataType, op.Key)
		if depend == nil {
			return
		}
		be := depend.Be
		valueString, _ := logic.AdditionMapId(mapNoId, be.BeDependType, op.Value)
		logic.execute.RemoveDepend(conn, structure.NewBaseData(be.BeDependType, valueString), dd, be.BeDepend, be.Depend)
	case AddRelation:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.AddRelation(conn, structure.NewBaseData(pdt, valueString), dd, op.Key)
	case RemoveRelation:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.RemoveRelation(conn, structure.NewBaseData(pdt, valueString), dd, op.Key)
	case AddLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.AddLink(conn, structure.NewBaseData(pdt, valueString), dd, op.Key)
	case RemoveLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.RemoveLink(conn, structure.NewBaseData(pdt, valueString), dd, op.Key)
	case AddToLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.AddLink(conn, dd, structure.NewBaseData(pdt, valueString), op.Key)
	case RemoveFromLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.RemoveLink(conn, dd, structure.NewBaseData(pdt, valueString), op.Key)
	case AddTimeLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.AddTimeLink(conn, structure.NewBaseData(pdt, valueString), dd, op.Key, logic.FormatTime(op.Time))
	case RemoveTimeLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.RemoveTimeLink(conn, structure.NewBaseData(pdt, valueString), dd, op.Key)
	case AddToTimeLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.AddTimeLink(conn, dd, structure.NewBaseData(pdt, valueString), op.Key, logic.FormatTime(op.Time))
	case RemoveFromTimeLink:
		pdt := structure.PublicDataType(op.Index)
		valueString, _ := logic.AdditionMapId(mapNoId, pdt, op.Value)
		logic.execute.RemoveTimeLink(conn, dd, structure.NewBaseData(pdt, valueString), op.Key)
	}
}

func (logic *LogicExecute) addDepend(accountId int, target *structure.BaseData, operate *UpdateOperateContent, notice *NoticeContent, noticeData *UpdateContent, fd *FieldsDefine, instance *MapInstance, allMap map[string][]interface{}) (*NoticeContent, []byte, *chess_protocol.UpdateData) {
	var r *structure.BaseData
	depend := logic.DefaultDepend(target.DataType, operate.Key)
	if depend == nil {
		return nil, nil, nil
	}
	be := depend.Be
	if be.BeDependIsPosition {
		r = structure.NewBaseData(be.BeDependType, utils.ToBytes(operate.Value))
	} else if be.BeDependIsNo {
		r = structure.NewBaseData(be.BeDependType, utils.ToInt(operate.Value))
	} else {
		r = structure.NewBaseData(be.BeDependType, utils.ToString(operate.Value))
	}

	noticeData.Dependents = append(noticeData.Dependents, &DependentItem{
		Key:    operate.Key,
		Depend: r,
	})
	noticeData.Inherit = true
	if be.BeDependType == AccountType {
		// 设定account变更
		notice.NewAccountId = utils.ToInt(operate.Value)
	}
	noticeData.Props = append(noticeData.Props, UpdateField{
		Key:   operate.Key,
		Value: operate.Value,
	})

	if be.Index == -1 || fd == nil {
		// 非定义
		return nil, nil, nil
	}
	//fmt.Println("add depend", depend)
	updateData := chess_protocol.UpdatePublicData{}

	if fd.IsPosition {
		updateData.ListNode = []chess_protocol.UpdateListNode{
			{Key: be.Index, Logic: true, Value: utils.ToBytes(target.Id)},
		}
	} else if fd.IsNo {
		updateData.ListNo = []chess_protocol.UpdateListNo{
			{Key: be.Index, Logic: true, Value: utils.ToInt(target.Id)},
		}
	} else if fd.IsId {
		updateData.ListId = []chess_protocol.UpdateListId{
			{Key: be.Index, Logic: true, Value: utils.ToString(target.Id)},
		}
	}
	n := &NoticeContent{
		OldAccountId: accountId,
		NewAccountId: accountId,
		Data:         *r,
		Content: UpdateContent{
			UpdatePublicData: &updateData,
		},
	}
	if fd := logic.GetFieldsDefine(r.DataType); fd == nil || !fd.IsChess {
		return n, nil, nil
	}

	pp := logic.GetPropCache(instance, r, Position)
	if pp == nil {
		return n, nil, nil
	}
	//location := logic.GetPropCache(conn, mapNoId, r.DataType, r.Id, Location)
	//ps := utils.ToString(location)
	ii := &chess_protocol.UpdateData{
		DataType: byte(r.DataType),
		Id:       r.Id,
		Data:     updateData,
	}

	return n, utils.ToBytes(pp), ii
}

func (logic *LogicExecute) removeDepend(accountId int, target *structure.BaseData, operate *UpdateOperateContent, notice *NoticeContent, noticeData *UpdateContent, fd *FieldsDefine, instance *MapInstance, allMap map[string][]interface{}) (*NoticeContent, []byte, *chess_protocol.UpdateData) {
	var r *structure.BaseData
	depend := logic.DefaultDepend(target.DataType, operate.Key)
	if depend == nil {
		return nil, nil, nil
	}
	be := depend.Be
	//fmt.Println("remove depend", updateOperateData.Data, operate, depend)
	if be.BeDependIsPosition {
		r = structure.NewBaseData(be.BeDependType, utils.ToBytes(operate.Value))
	} else if be.BeDependIsNo {
		r = structure.NewBaseData(be.BeDependType, utils.ToInt(operate.Value))
	} else {
		r = structure.NewBaseData(be.BeDependType, utils.ToString(operate.Value))
	}
	noticeData.Dependents = append(noticeData.Dependents, &DependentItem{
		Key:    operate.Key,
		Depend: structure.NewBaseData(r.DataType, nil),
	})

	noticeData.Props = append(noticeData.Props, UpdateField{
		Key:   operate.Key,
		Value: nil,
	})
	noticeData.Inherit = true

	if be.Index == -1 || fd == nil {
		// 非定义
		return nil, nil, nil
	}
	updateData := chess_protocol.UpdatePublicData{}
	if fd.IsPosition {
		updateData.ListNode = []chess_protocol.UpdateListNode{
			{Key: be.Index, Logic: false, Value: utils.ToBytes(target.Id)},
		}
	} else if fd.IsNo {
		updateData.ListNo = []chess_protocol.UpdateListNo{
			{Key: be.Index, Logic: false, Value: utils.ToInt(target.Id)},
		}
	} else if fd.IsId {
		updateData.ListId = []chess_protocol.UpdateListId{
			{Key: be.Index, Logic: false, Value: utils.ToString(target.Id)},
		}
	}
	n := &NoticeContent{
		OldAccountId: accountId,
		NewAccountId: accountId,
		Data:         *r,
		Content: UpdateContent{
			UpdatePublicData: &updateData,
		},
	}
	if fd := logic.GetFieldsDefine(r.DataType); fd == nil || !fd.IsChess {
		return n, nil, nil
	}

	pp := logic.GetPropCache(instance, r, Position)
	if pp == nil {
		return n, nil, nil
	}

	//location := logic.GetPropCache(conn, mapNoId, r.DataType, r.Id, Location)
	//ps := utils.ToString(location)
	ii := &chess_protocol.UpdateData{
		DataType: byte(r.DataType),
		Id:       r.Id,
		Data:     updateData,
	}
	return n, utils.ToBytes(pp), ii
}
